package com.offics.frame.infrastructure.aop;

import com.offics.frame.application.dto.ResponseDTO;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Arrays;

/**
 * 日志切面
 * 用于记录接口调用日志
 */
@Aspect
@Component
@Slf4j
public class LogAspect {

    /**
     * 定义切入点，拦截interfaces.rest包下的所有方法
     */
    @Pointcut("execution(public * com.offics.frame.interfaces.rest..*.*(..))")
    public void webLog() {
    }

    /**
     * 前置通知：在接口调用前记录请求信息
     * 
     * @param joinPoint 切点
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();

            // 记录请求信息
            log.info("请求URL: {}", request.getRequestURL().toString());
            log.info("请求方法: {}", request.getMethod());
            log.info("请求IP: {}", request.getRemoteAddr());
            log.info("调用方法: {}.{}", joinPoint.getSignature().getDeclaringTypeName(),
                    joinPoint.getSignature().getName());
            log.info("请求参数: {}", Arrays.toString(joinPoint.getArgs()));
        }
    }

    /**
     * 后置通知：在接口调用后记录响应信息
     * 
     * @param result 返回结果
     */
    @AfterReturning(returning = "result", pointcut = "webLog()")
    public void doAfterReturning(Object result) {
        // 记录返回结果
        if (result instanceof ResponseDTO) {
            ResponseDTO<?> response = (ResponseDTO<?>) result;
            log.info("响应状态码: {}", response.getCode());
            log.info("响应消息: {}", response.getMessage());
            // 避免记录过大的响应数据
            log.debug("响应数据: {}", response.getData());
        } else {
            log.info("响应结果: {}", result);
        }
    }
}